<?php
/**
 * RAI(Remote Access Interface)客户端
 *
 *
 * @author iwind <iwind.iwind@gmail.com>
 * @link http://www.4kiki.net/
 * @version $Id: RaiClient.php 312 2008-04-23 16:29:38Z iwind $
 * @package net.4kiki.rai.client
 */

import("net.4kiki.rai.format.*");

/**
 * RAI客户端
 * 
 * @version $Id: RaiClient.php 312 2008-04-23 16:29:38Z iwind $
 * @package net.4kiki.rai.client
 * @since 0.0.3
 */
class RaiClient {
	private $uri;
	/**
	 * Enter description here...
	 *
	 * @var RaiFormat
	 */
	private $format;
	private $responseBody;
	
	/**
	 * 构造器
	 *
	 * @param string $uri 服务的uri
	 * @param RaiFormat $format 传输数据使用的格式
	 */
	public function __construct($uri, RaiFormat $format) {
		$this->uri = $uri;
		$this->format = $format;
	}
	
	/**
	 * 调用方法
	 *
	 * @param string $method 方法名
	 * @param array|null $arguments 参数
	 * @return RaiResponse
	 */
	public function call($method, $arguments = null) {
		if ($arguments === null) {
			$arguments = array();
		}
		if (!is_array($arguments)) {
			throw new RaiException("arguments must be an array");
		}
		$pieces = explode(".", $method);
		if (empty($pieces)) {
			throw new RaiException("method must not be empty");
		}
		foreach ($pieces as $piece) {
			if (!preg_match("/^[a-z_]\w*$/i", $piece)) {
				throw new RaiException("method '{$method}' contains invalid piece '{$piece}'");
			}
		}
		if (count($pieces) == 1) {
			throw new RaiException("please declare a service name which has method '{$method}'");
		}
		$method = array_pop($pieces);
		$serviceName = implode(".", $pieces);
			
		$http = new IHttpClient($this->uri);
		$http->setContentType($this->format->getContentType());
		$http->setBody($this->format->encodeRequest(new RaiRequest($serviceName, $method, $arguments)));;
		$httpResponse = $http->request(IHttpClient::POST_METHOD);
		
		if ($httpResponse->getStatus() != 200) {
			throw new RaiException("server " . $httpResponse->getStatus() . " error.");
		}
		$this->responseBody = $httpResponse->getBody();

		$response = $this->format->decodeResponse($this->responseBody);
		return $response;
	}
	
	/**
	 * 取得代理
	 *
	 * @param string $serviceName 服务名
	 * @return RaiProxy
	 */
	public function getProxy($serviceName) {
		return new RaiProxy($this, $serviceName);
	}
	
	/**
	 * 取得响应主体内容
	 *
	 * @return string
	 */
	public function getResponseBody() {
		return $this->responseBody;
	}
}

?>